package com.github.ilioili.justdoit.widget;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import java.util.Calendar;
import java.util.LinkedList;

/**
 * Created by hantuo on 16/5/10.
 */
public class MonthView extends ViewGroup {
    private int year;
    private int month;
    private int firstDayOfWeek;
    private int dayCountOfMonth;
    private int rowHeight;
    private int rowWidth;
    private LinkedList<View> viewCache = new LinkedList<>();

    public MonthView(Context context) {
        super(context);
    }

    public MonthView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MonthView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public MonthView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        ViewGroup viewGroup = (ViewGroup) getParent();
        if (width == 0) {
            width = viewGroup.getMeasuredWidth() - viewGroup.getPaddingLeft() - viewGroup.getPaddingRight();
        }
        if (getChildCount() > 0) {
            measureChildren(MeasureSpec.makeMeasureSpec(width / 7, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            rowHeight = getChildAt(0).getMeasuredHeight();
        } else {
            rowHeight = MeasureSpec.getSize(heightMeasureSpec) / 7;
        }
        rowWidth = width / 7;
        int rowCount = (dayCountOfMonth + firstDayOfWeek) / 7 + 1;
        setMeasuredDimension(rowWidth * 7, rowHeight * rowCount);
        int widthSpec = MeasureSpec.makeMeasureSpec(rowWidth, MeasureSpec.EXACTLY);
        int heightSpec = MeasureSpec.makeMeasureSpec(rowHeight, MeasureSpec.EXACTLY);
        measureChildren(widthSpec, heightSpec);
        forceLayout();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int width = getMeasuredWidth();
        for (int i = 0; i < dayCountOfMonth; i++) {
            int column = (i + firstDayOfWeek) % 7;
            int row = (i + firstDayOfWeek) / 7;
            getChildAt(i).layout(width * column / 7, rowHeight * row, width * (column + 1) / 7, rowHeight * (row + 1));
        }
    }

    /**
     * @param month 从0开始
     */
    public void setMonth(int year, int month) {
        this.year = year;
        this.month = month;
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, 1);
        dayCountOfMonth = calendar.getActualMaximum(Calendar.DATE);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        firstDayOfWeek -= 2;
        if (firstDayOfWeek == -1) {
            firstDayOfWeek = 6;
        }
        freshView();
    }

    public void freshView() {
        removeViewToCache();
        for (int i = 1; i <= dayCountOfMonth; i++) {
            View view = adapter.getView(viewCache.poll(), year, month, i);
            view.invalidate();
            addViewInLayout(view, i - 1, view.getLayoutParams(), true);
        }
        requestLayout();
    }


    public int getRow(View view) {
        return view.getTop() / rowHeight;
    }

    public int getColumn(View view) {
        return view.getLeft() / view.getMeasuredWidth();
    }

    private void removeViewToCache() {
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            viewCache.add(getChildAt(i));
        }
        removeAllViewsInLayout();
    }

    public Adapter adapter;

    public void setAdapter(Adapter adapter) {
        this.adapter = adapter;
    }

    public static abstract class Adapter {
        /**
         * @param view
         * @param year
         * @param month 从0开始，0代表1月
         * @param day   从0开始，0代表1号
         * @return
         */
        public abstract View getView(View view, int year, int month, int day);
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(state);
        freshView();
    }
}
